package com.yunti.yntk.manager;

import android.content.Context;
import android.content.SharedPreferences;
import com.yunti.yntk.model.PointPosition;
import com.yunti.yntk.util.NumberUtils;

import java.text.NumberFormat;

import static java.lang.Math.*;

public class ComputScoreManager {
    private static ComputScoreManager singletonHungary = new ComputScoreManager();
    private NumberFormat nf = NumberFormat.getInstance();

    //跳远，分别对应起跳线、起跳线前、起跳线后
    public final static int TY_1 = 1;
    public final static int TY_2 = 2;
    public final static int TY_3 = 3;
    //投掷
    public final static int QQ = 4;
    public final static int BQ = 5;
    public final static int LQ = 6;
    public final static int TB = 7;
    //比赛模式
    private int gamemode = TY_1;


    //投掷圈半径
    private double throw_cd_qq = 1.0675;
    //投掷圈半径
    private double throw_cd_bq = 8;
    //投掷圈半径
    private double throw_cd_lq = 1.25;
    //投掷圈半径
    private double throw_cd_tb = 1.25;


    //投掷圈圆心到仪器距离
    private double throw_m;

    //仪器到起跳线的距离
    private double h = 0;
    double ta = 0;
    int state = 1;

    private double a_hd;
    private double a_angle;

    private double b_hd;
    private double b_angle;

    private double constant;

    private SharedPreferences sp;

    private SharedPreferences.Editor editor;

    //是否初始化过算法
    private boolean isInit = false;

    public boolean isInit() {
        return isInit;
    }

    public int getGamemode() {
        return gamemode;
    }

    //将构造器设置为private禁止通过new进行实例化
    private ComputScoreManager() {
        nf.setMaximumFractionDigits(3);
    }

    public static ComputScoreManager getInstance() {
        return singletonHungary;
    }

    public void init(Context context) {
        sp = context.getSharedPreferences("scoreapi", 0);
        editor = sp.edit();

        this.isInit = sp.getBoolean("isInit", false);
        this.gamemode = sp.getInt("gamemode", 0);
        this.a_angle = sp.getFloat("a_angle", 0);
        this.a_hd = sp.getFloat("a_hd", 0);
        this.b_angle = sp.getFloat("b_angle", 0);
        this.b_hd = sp.getFloat("b_hd", 0);
        this.state = sp.getInt("state", 1);
        this.ta = sp.getFloat("ta", 0);
        this.h = sp.getFloat("h", 0);
        this.throw_m = sp.getFloat("throw_m", 0);
        this.constant = sp.getFloat("constant", 0);

    }

    //得到成绩。根据gamemode选择相应算式
    public double getScore(PointPosition point) {
        double angle = point.getAngle();
        double distance = point.getDistance();
        if (Double.isNaN(angle) || Double.isNaN(distance)) return 0.0;
        switch (gamemode) {
            case TY_1:
                return getTy_1Score(angle, distance);
            case TY_2:
                return getTy_2Score(angle, distance);
            case TY_3:
                return getTy_3Score(angle, distance);
            case QQ:
                return getThromScore(angle, distance);
            case LQ:
                return getThromScore(angle, distance);
            case TB:
                return getThromScore(angle, distance);
            case BQ:
                return getThromScore(angle, distance);
            default:
                return 0.0;
        }
    }

    private double getTy_1Score(double angel, double distance) {
        double score = 0;
        if (angel >= 180) angel = 360 - angel;
        score = distance * sin(angel * PI / 180) + constant / 1000.0;
        score = NumberUtils.numformat(score, 3);
        return score;
    }

    private double getTy_2Score(double angel, double distance) {
        double score = 0;
        if (state == 1) {
            score = distance * sin(((angel - b_angle) * PI / 180) - ta) + h + constant / 1000.0;
        } else
            score = distance * sin((angel * PI / 180) - ta) + h + constant / 1000.0;
        score = NumberUtils.numformat(score, 3);
        return score;
    }

    private double getTy_3Score(double angel, double distance) {
        double score = 0;
        if (state == 1) {
            score = distance * sin(((angel - b_angle) * PI / 180) + ta) - h + constant / 1000.0;
        } else
            score = (distance * sin((angel * PI / 180) + ta)) - h + constant / 1000.0;
        score = NumberUtils.numformat(score, 3);
        return score;
    }

    //得到投掷成绩
    private double getThromScore(double angel, double distance) {
        double score = 0;
        if (angel >= 180) angel = 360 - angel;
        score = sqrt(throw_m * throw_m + distance * distance - 2 * throw_m * distance * cos(angel * PI / 180)) + constant / 1000.0;
        if (gamemode == QQ) score = Double.parseDouble(nf.format(score - throw_cd_qq));
        if (gamemode == BQ) score = Double.parseDouble(nf.format(score - throw_cd_bq));
        if (gamemode == LQ) score = Double.parseDouble(nf.format(score - throw_cd_lq));
        if (gamemode == TB) score = Double.parseDouble(nf.format(score - throw_cd_tb));
        return score;
    }


    public void setThrow_m(double throw_m) {
        this.throw_m = throw_m;
    }

    public void setaPoint(PointPosition point) {
        this.a_angle = point.getAngle();
        this.a_hd = point.getDistance();


        editor.apply();

    }

    public void setbPoint(PointPosition point) {
        this.b_hd = point.getDistance();
        this.b_angle = point.getAngle();

    }


    public void computeH() {
        double tac;
        double tacAngle;

        double tbc;
        double tbcAngle;

        if (gamemode == 2) {
            if (b_angle - a_angle <= 180) {
                tac = b_hd;
                tacAngle = 0;
                tbc = a_hd;
                tbcAngle = 360 - b_angle;
                state = 1;
            } else {
                tac = a_hd;
                tacAngle = a_angle;
                tbc = b_hd;
                tbcAngle = b_angle;
                state = 0;
            }
        } else if (gamemode == 3) {
            if (b_angle - a_angle <= 180) {
                tac = a_hd;
                tacAngle = a_angle;
                tbc = b_hd;
                tbcAngle = b_angle;
                state = 0;
            } else {
                tac = b_hd;
                tacAngle = 0;
                tbc = a_hd;
                tbcAngle = 360 - b_angle;
                state = 1;
            }
        } else return;

        double acbAngle = tbcAngle;
        if (acbAngle >= 180) acbAngle = 360 - acbAngle;

        double s = 0.5 * tac * tbc * sin(acbAngle * PI / 180);
        double ab =
                sqrt(tac * tac + tbc * tbc - 2 * tac * tbc * cos(acbAngle * PI / 180));

        ta = acos((tac * tac + ab * ab - tbc * tbc) / (2 * tac * ab));
        h = (s * 2) / ab;
        h = Math.abs(h);
//        System.out.println("AC:" + tac);
//        System.out.println("AB:" + ab);
//        System.out.println("BC:" + tbc);
//        System.out.println("面积:" + s);
//        System.out.println("两边夹角:" );
//        System.out.println("两点相距:");
//        System.out.println("弧度:");
//        System.out.println("角:");
//        System.out.println("高:");
    }

    public void saveParameter() {
        editor.putBoolean("isInit", true);
        editor.putInt("gamemode", gamemode);
        editor.putFloat("a_angle", (float) a_angle);
        editor.putFloat("a_hd", (float) a_hd);
        editor.putFloat("b_angle", (float) b_angle);
        editor.putFloat("b_hd", (float) b_hd);
        editor.putInt("state", state);
        editor.putFloat("ta", (float) ta);
        editor.putFloat("h", (float) h);
        editor.putFloat("throw_m", (float) throw_m);
        editor.apply();
    }

    public void setGamemode(int gamemode) {
        this.gamemode = gamemode;
        this.isInit = true;
    }

    public double getConstant() {
        return constant;
    }

    public void setConstant(double constant) {
        this.constant = constant;
        editor.putFloat("constant", (float) constant);
        editor.apply();
    }

    public String getOriginaldata(PointPosition point) {
        if (gamemode == TY_1) {
            return "mode:ty1;angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }
        if (gamemode == TY_2) {
            return "mode:ty2;a_angle:" + a_angle + ";ahd:" + a_hd + ";b_angle:" + b_angle + ";b_hd:" + b_hd + ";angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }

        if (gamemode == TY_3) {
            return "mode:ty3;a_angle:" + a_angle + ";ahd:" + a_hd + ";b_angle:" + b_angle + ";b_hd:" + b_hd + ";angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }

        if (gamemode == QQ) {
            return "mode:qq;throw_m:" + throw_m + ";angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }

        if (gamemode == BQ) {
            return "mode:bq;throw_m:" + throw_m + ";angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }

        if (gamemode == LQ) {
            return "mode:lq;throw_m:" + throw_m + ";angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }

        if (gamemode == TB) {
            return "mode:tb;throw_m:" + throw_m + ";angle:" + point.getAngle() + ";hd:" + point.getDistance();
        }
        return "";
    }


}
